import os
import json
import random
import string
import ipaddress
import socket

from urllib.parse import urlparse
from functools import lru_cache

from ip2geotools.databases.noncommercial import DbIpCity
from ip2geotools.errors import LocationError

from user_agents import parse
from settings.utils import get_setting


@lru_cache
def get_ip_info(ip):
    """
    return e.g: {'ip_address': '51.195.223.55', 'city': 'London', 'region': 'England', 'country': 'GB', 'latitude': 51.5073219, 'longitude': -0.1276474}
    """
    try:
        ip = ipaddress.ip_address(ip)
        return json.loads(DbIpCity.get(str(ip), api_key='free').to_json())
    except (ValueError, LocationError, json.JSONDecodeError):
        return {}


def get_device_type(user_agent):
    from .models import Stat

    if user_agent.is_mobile:
        return Stat.DEVICE_TYPE.MOBILE

    if user_agent.is_pc:
        return Stat.DEVICE_TYPE.DESKTOP

    if user_agent.is_tablet:
        return Stat.DEVICE_TYPE.TABLET

    return Stat.DEVICE_TYPE.UNKNOWN


@lru_cache
def user_agent_parser(raw_user_agent):
    return parse(raw_user_agent)


def generate_random_slug():
    from .models import Link

    chars = string.digits + string.ascii_letters
    slug = ''.join(random.choices(chars, k=random.randint(1, 6)))

    if Link.objects.filter(slug__exact=slug).exists():
        return generate_random_slug()
    return slug


def get_referer(req):
    if req.method == 'POST':
        return req.POST.get('referer', None)

    return req.META.get('HTTP_REFERER', None)


def get_domain_ip(domain):
    # parse just the domain name from the url/domain (clean up)
    domain = urlparse(domain).netloc

    try:
        return socket.gethostbyname(domain)
    except IOError as e:
        pass
    return None


def get_valid_ips():
    ips = get_setting('VALID_IPS')
    return ips.strip().split('\n')
